package com.woniu51.zuul.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.woniu.common.constant.UserConstants;
import com.woniu.common.core.redis.RedisCache;
import com.woniu.common.utils.token.AccToken;
import com.woniu.common.utils.token.JwtTokenUtils;
import org.apache.http.HttpStatus;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author 杨光
 * @date 2022年03月29日 16:04
 */
@Component
public class LoginFilter extends ZuulFilter {


    @Autowired
    private RedisCache redisCache;

    private Set<String> whiteNameList=new HashSet();


    @PostConstruct
    public void initWhiteNameList(){
        List<String> unauthUrlList = redisCache.getCacheList(UserConstants.REDIS_UNAUTH_URL_PREFIX);

        System.out.println(unauthUrlList);

        whiteNameList.addAll(unauthUrlList);

        System.out.println(whiteNameList);

    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    exchange = @Exchange(name = UserConstants.MQ_REFRESH_UNAUTH_URL_EXCHANGE,
                            type = ExchangeTypes.TOPIC),
                    value = @Queue(value = UserConstants.MQ_REFRESH_UNAUTH_URL_QUEUE, durable = "true"),
                    key = {UserConstants.MQ_REFRESH_UNAUTH_URL_ROUTING_KEY}
            )
    })
    public void receiveUpdateRedisMessage(String msg){
        System.out.println("msg=="+msg);
        //重新从redis中获取url 列表更新本地缓存
        initWhiteNameList();
    }

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        String requestURI = request.getRequestURI();
        if (whiteNameList.contains(requestURI)) {
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {

        //验证token是否有效
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        HttpServletResponse response = requestContext.getResponse();

        //从请求头里面获取jwt
        String jwtHeader = request.getHeader("Authorization");
        AccToken accToken = parseToken(jwtHeader);

        //从请求参数中获取jwt
        if(accToken == null){
            String jwtParam = request.getParameter("acctoken");
            accToken =parseToken(jwtParam);
        }


        if(accToken==null){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
        }else{
            //如果验证成功，把userid添加到request头中，给后面的微服务使用
            requestContext.addZuulRequestHeader("userid",""+accToken.getUserId());
            requestContext.addZuulRequestHeader("userAccount",accToken.getUserAccount());
        }

        return null;

    }

    private AccToken parseToken(String jwtHeader){
        AccToken accToken = null;

        if(jwtHeader==null){
            return null;
        }
//        客户端传过来的时候前面增加了个固定字符串,所以把前面的7个字符截掉
//        "Bearer eyJhbGciOiJIUzUxMiJ9.eyJqd3RfY2xhaW1zX2tleSI6IntcInVzZXJJZFwiOjEsXCJ1c2VyTmFtZVwiOlwi566h55CG5ZGYXCIsXCJ1c2VyQWNjb3VudFwiOlwiYWRtaW5cIixcImV4cGlyZURhdGVUaW1lXCI6MTY0ODY5MzE3MDk5NX0ifQ.6Wo4XP2ynopOLW3VE9cFFUMC0m4_vPIRf8riAam3CMolJmd9nFb3aTgkXYnk1lwgdxL7FdC7V43VUWsMWDpGPA"
        String jwt  = jwtHeader.substring(7);
        //这里我们要判断一下，请求是从后端管理页面来的，还是从web端来的
        //1.如果从web端过来的请求，那么格式为：/api/微服务路径/web/**
        //2.如果是后端管理页面来的请求，那么给为:/api/微服务路径/**

        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String requestURI = request.getRequestURI();
        String[] split = requestURI.split("/");
        if("web".equals(split[3])){
            //解析web端的token
            accToken = JwtTokenUtils.parseWebJwtToken(jwt);
        }else{
            //解析管理页面的token
            accToken = JwtTokenUtils.parseAdminJwtToken(jwt);
        }
        return accToken;
    }

    public static void main(String[] args) {
        String url="/api/abc/web/aaa";
        String[] split = url.split("/");
        for (String s : split) {

            System.out.println(s);
        }
    }
}
